/***************************************************************************
 *   Copyright (C) 2007 to 2009 by Andreas Theofilu                        *
 *   andreas@theosys.at                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation version 3 of the License.                *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef _GANT_H
#define _GANT_H

#include <qstring.h>
#include <qfile.h>

#define MAXMSG 12 // SYNC,LEN,MSG,data[8],CHKSUM
#define hexval(c) ((c >= '0' && c <= '9') ? (c-'0') : ((c&0xdf)-'A'+10))

#define EVENT_RX_ACKNOWLEDGED		0x9b
#define EVENT_RX_BROADCAST		0x9a
#define EVENT_RX_BURST_PACKET		0x9c
#define EVENT_RX_EXT_ACKNOWLEDGED	0x9e
#define EVENT_RX_EXT_BROADCAST		0x9d
#define EVENT_RX_EXT_BURST_PACKET	0x9f
#define EVENT_TRANSFER_TX_COMPLETED	0x05
#define INVALID_MESSAGE			0x28
#define MESG_ACKNOWLEDGED_DATA_ID	0x4f
#define MESG_ASSIGN_CHANNEL_ID		0x42
#define MESG_BROADCAST_DATA_ID		0x4e
#define MESG_BURST_DATA_ID		0x50
#define MESG_CAPABILITIES_ID		0x54
#define MESG_CHANNEL_ID_ID		0x51
#define MESG_CHANNEL_MESG_PERIOD_ID	0x43
#define MESG_CHANNEL_RADIO_FREQ_ID	0x45
#define MESG_CHANNEL_SEARCH_TIMEOUT_ID	0x44
#define MESG_CHANNEL_STATUS_ID		0x52
#define MESG_CLOSE_CHANNEL_ID		0x4c
#define MESG_DATA_SIZE			13	// due to dodgy msg from suunto
#define MESG_EXT_ACKNOWLEDGED_DATA_ID	0x5e
#define MESG_EXT_BROADCAST_DATA_ID	0x5d
#define MESG_EXT_BURST_DATA_ID		0x5f
#define MESG_NETWORK_KEY_ID		0x46
#define MESG_OPEN_CHANNEL_ID		0x4b
#define MESG_OPEN_RX_SCAN_ID		0x5b
#define MESG_REQUEST_ID			0x4d
#define MESG_RESPONSE_EVENT_ID		0x40
#define MESG_RESPONSE_EVENT_SIZE	3
#define MESG_SEARCH_WAVEFORM_ID		0x49
#define MESG_SYSTEM_RESET_ID		0x4a
#define MESG_TX_SYNC			0xa4
#define MESG_UNASSIGN_CHANNEL_ID	0x41
#define RESPONSE_NO_ERROR		0x00

#define ACKSIZE 8		// above structure must be this size
#define AUTHSIZE 24		// ditto
#define PAIRSIZE 16

struct msg_queue
{
	uchar msgid;
	uchar len;
};

struct ack_msg
{
	uchar code;
	uchar atype;
	uchar c1;
	uchar c2;
	uint id;
};

struct auth_msg
{
	uchar code;
	uchar atype;
	uchar phase;
	uchar u1;
	uint id;
	ulong auth1;
	ulong auth2;
	ulong fill1;
	ulong fill2;
};

struct pair_msg
{
	uchar code;
	uchar atype;
	uchar phase;
	uchar u1;
	uint id;
	char devname[8];
};

class ant
{
	public:
	   ant ();
	   ~ant ();

	   bool setDevice (const QFile &fl);
	   bool setDevice (const QString &fl);
	   bool commfn ();	// Start reading data from device

	   // Basic functions to manage the device
	   bool ANT_ResetSystem ();
	   bool ANT_Cmd55 (uchar chan);
	   bool ANT_OpenRxScanMode (uchar chan);
	   bool ANT_Init ();
	   bool ANT_RequestMessage (uchar chan, uchar mesg);
	   bool ANT_SetNetworkKeya (uchar net, uchar *key);
	   bool ANT_SetNetworkKey (uchar net, uchar *key);
	   bool ANT_AssignChannel (uchar chan, uchar chtype, uchar net);
	   bool ANT_UnAssignChannel (uchar chan);
	   bool ANT_SetChannelId (uchar chan, ushort dev, uchar devtype, uchar manid);
	   bool ANT_SetChannelRFFreq (uchar chan, uchar freq);
	   bool ANT_SetChannelPeriod (uchar chan, ushort period);
	   bool ANT_SetChannelSearchTimeout (uchar chan, uchar timeout);
	   bool ANT_SetSearchWaveform (uchar chan, ushort waveform);
	   bool ANT_SendAcknowledgedDataA (uchar chan, uchar *data);
	   bool ANT_SendAcknowledgedData (uchar chan, uchar *data);
	   unsigned short ANT_SendBurstTransferA(uchar chan, uchar *data, unsigned short numpkts);
	   unsigned short ANT_SendBurstTransfer (uchar chan, uchar *data, unsigned short numpkts);
	   bool ANT_OpenChannel (uchar chan);
	   bool ANT_CloseChannel (uchar chan);
	   int ANT_fd();

	public:
	   typedef bool (ant::*RESPONSE_FUNC)(uchar chan, uchar msgid);
	   typedef bool (ant::*CHANNEL_EVENT_FUNC)(uchar chan, uchar event);
	   void ANT_AssignResponseFunction (RESPONSE_FUNC rf, uchar* rbuf);
	   void ANT_AssignChannelEventFunction (uchar chan, CHANNEL_EVENT_FUNC rf, uchar* rbuf);

	protected:
	   bool msg_send(uchar mesg, uchar *inbuf, uchar len);
	   bool msg_send(uchar mesg, uchar data1, uchar data2);
	   bool msg_send(uchar mesg, uchar data1, uchar data2, uchar data3);
	   bool get_data(int fd);

	private:
	   QFile device;
	   bool qFile;
	   int commenabled;
	   RESPONSE_FUNC rfn;
	   CHANNEL_EVENT_FUNC cfn;
	   uchar *rbufp;
	   uchar *cbufp;
};

class gant : public ant
{
	public:
	   gant (const QString &af);
	   ~gant ();

	   bool read_device ();
	   QString getBufferName () { return tmpOut.fileName (); };
	   uchar *getBuffer(int *size);
	
	protected:
	   uint randno ();
	   bool chevent (uchar chan, uchar event);
	   bool revent (uchar chan, uchar event);

	private:
	   uchar cbuf[MESG_DATA_SIZE]; // channel event data gets stored here
	   uchar ebuf[MESG_DATA_SIZE]; // response event data gets stored here

	   bool authfd;
	   QString authfile;
	   QFile faf, tmpOut;

	   uint mydev;
	   uint peerdev;
	   uint myid;
	   unsigned long myauth1;
	   unsigned long myauth2;
	   char authdata[33];

	   uchar clientid[3][8];

	   int state;		// state machine state
};

#endif
